#!/usr/bin/python

import os
import sys

from Configurator import Configurator
from ClientUpdater import ClientUpdater
from pysvn import ClientError

class BadConfigError(Exception):
    pass

class Subcon:
    def __init__(self,options):
        self.options    = options
        self.cmd_map = { 'add': {}, 'mod': {}, 'del':{} }
        self.actions    = {}
        config     = { 
            'exclude_file'  : '/etc/systemimager/updateclient.local.exclude',
            'update_script' : '/usr/sbin/si_updateclient',
            'temp_dir'      : '/tmp',
            'repo_url'      : None,
            'server_name'   : None,
            'image_name'    : None,
            'user_name'     : None,
            'password'      : None,
            'default_to_base' : False,
            'services'      : {},
        }

        try:
            execfile(self.options.configfile, config)
        except:
            raise BadConfigError("Failed to parse config file")

        if not (config['server_name'] and config['image_name'] and config['repo_url']):
            raise BadConfigError("Missing required config directives")

        self.configurator = Configurator(config['repo_url'], options.role, config['default_to_base'], options.release, config['temp_dir'], config['user_name'], config['password'])
        self.client_updater = ClientUpdater(config['exclude_file'], config['update_script'], config['server_name'], config['image_name'])
        self.config = config
        self.buildCommandMap()

    def __del__(self):
        if self.configurator:
            self.configurator.cleanup()

    def buildCommandMap(self):
        for service in self.config['services'].values():
            for file in service['files']:
                for command in ['add', 'mod', 'del']:
                    if service['commands'].has_key(command):
                        if not self.cmd_map[command].has_key(file): self.cmd_map[command][file] = []
                        self.cmd_map[command][file].append( service['commands'][command] )

    def addAction(self,command,path):
        if not os.path.isabs(path):
            path = os.path.join('/',path)
        if self.cmd_map[command].has_key(path):
            for action in self.cmd_map[command][path]:
                self.actions[action] = 1
                return True
        return False

    def runPostUpdateActions(self):
         for action in self.actions.keys():
            rv = os.system(action)
            if rv != 0: 
                print "WARNING: command [%s] did not succeed!"

    def doUpdate(self):
        (managed_files, managed_dirs) = self.configurator.getManagedFiles()
        self.client_updater.exclude_paths = managed_files + [self.configurator.temp_dir]
        (new, changed, same) = self.configurator.diffTree()

        for path in new:
            self.addAction('add', path)
        for path in changed:
            self.addAction('mod', path)

        if self.options.dry_run:
            if self.options.do_sync:
                self.client_updater.updateClient(dry_run=True)
            print "The following commands would be run:"
            for action in self.actions.keys():
                print action

        else:
            if self.options.do_sync:
                self.client_updater.updateClient()
            self.configurator.writeConfig()
            self.runPostUpdateActions()
